import dayjs from "@/utils/dayjs.ts";
import mino from "@/data/mino.json"
import _ from "lodash";
import { defaultCourt } from "./defaultCourt"
import { fullArray, RafTimer } from "./utils";

// 枚举mode
enum GameMode {
    'zen' = '禅',
    '10L' = '消除10行',
    '40L' = '消除40行',
    '200L' = '消除200行',
    '1000L' = '消除1000行',
    'confront_lv1' = '对抗 Lv1',
    'confront_lv2' = '对抗 Lv2',
    'confront_lv3' = '对抗 Lv3',
    'confront_lv4' = '对抗 Lv4',
    'one_lv1' = '狂热 Lv1',
    'one_lv2' = '狂热 Lv2',
    'one_lv3' = '狂热 Lv3',
    'one_lv4' = '狂热 Lv4',
    'survival_lv1' = '生存 Lv1',
    'survival_lv2' = '生存 Lv2',
    'survival_lv3' = '生存 Lv3',
    'survival_lv4' = '生存 Lv4',
    'excavate_lv1' = '挖掘 Lv1',
    'excavate_lv2' = '挖掘 Lv2',
    'excavate_lv3' = '挖掘 Lv3',
    'excavate_lv4' = '挖掘 Lv4',
    'classic' = '经典模式',
    'quickMatch' = '快速匹配',
}

const singleModeList = () => {
    return [
        {
            name: '禅',
            eName: 'ZEN',
            id: 'zen',
        },
        {
            name: '消行',
            eName: 'CLEAR LINES',
            // 子分类
            child: [
                {
                    name: '消除10行',
                    eName: '10 LINES',
                    id: '10L',
                },
                {
                    name: '消除40行',
                    eName: '40 LINES',
                    id: '40L',
                },
                {
                    name: '消除200行',
                    eName: '200 LINES',
                    id: '200L',
                },
                {
                    name: '消除1000行',
                    eName: '1000 LINES',
                    id: '1000L',
                },
            ]
        },
        {
            name: '对抗',
            eName: 'CONFRONT',
            // 子分类
            child: [
                {
                    name: '对抗 Lv1',
                    eName: 'CONFRONT LV1',
                    id: 'confront_lv1',
                },
                {
                    name: '对抗 Lv2',
                    eName: 'CONFRONT LV2',
                    id: 'confront_lv2',
                },
                {
                    name: '对抗 Lv3',
                    eName: 'CONFRONT LV3',
                    id: 'confront_lv3',
                },
                {
                    name: '对抗 Lv4',
                    eName: 'CONFRONT LV4',
                    id: 'confront_lv4',
                },
            ]
        },
        {
            name: '狂热',
            eName: 'ONE',
            // 子分类
            child: [
                {
                    name: '狂热 Lv1',
                    eName: 'ONE LV1',
                    id: 'one_lv1',
                },
                {
                    name: '狂热 Lv2',
                    eName: 'ONE LV2',
                    id: 'one_lv2',
                },
                {
                    name: '狂热 Lv3',
                    eName: 'ONE LV3',
                    id: 'one_lv3',
                },
                {
                    name: '狂热 Lv4',
                    eName: 'ONE LV4',
                    id: 'one_lv4',
                },
            ]
        },
        {
            name: '生存',
            eName: 'SURVIVAL',
            // 子分类
            child: [
                {
                    name: '生存 Lv1',
                    eName: 'SURVIVAL LV1',
                    id: 'survival_lv1',
                },
                {
                    name: '生存 Lv2',
                    eName: 'SURVIVAL LV2',
                    id: 'survival_lv2',
                },
                {
                    name: '生存 Lv3',
                    eName: 'SURVIVAL LV3',
                    id: 'survival_lv3',
                },
                {
                    name: '生存 Lv4',
                    eName: 'SURVIVAL LV4',
                    id: 'survival_lv4',
                },
            ]
        },
        {
            name: '挖掘',
            eName: 'EXCAVATE',
            // 子分类
            child: [
                {
                    name: '挖掘 Lv1',
                    eName: 'EXCAVATE LV1',
                    id: 'excavate_lv1',
                },
                {
                    name: '挖掘 Lv2',
                    eName: 'EXCAVATE LV2',
                    id: 'excavate_lv2',
                },
                {
                    name: '挖掘 Lv3',
                    eName: 'EXCAVATE LV3',
                    id: 'excavate_lv3',
                },
                {
                    name: '挖掘 Lv4',
                    eName: 'EXCAVATE LV4',
                    id: 'excavate_lv4',
                },
            ]
        },
        {
            name: '经典模式',
            eName: 'CLASSIC',
            id: 'classic',
        },
    ]
}

// 移动 旋转 

const tutorialModeList = () => {
    return [
        {
            name: '教程',
            eName: 'TUTORIAL',
            id: 'tutorial',
        },
    ]
}

interface CreateRubbishInfo {
    enable: boolean,
    frequency: number,
    count: number,
    createTimeMode: string,
    mode: string,
    oneRubbishX: number,
}

interface GameModeInfo {
    name: string,
    id: string,
    desc: string,
}

interface TetrisInfo {
    mode: string,
    bagRule: string,
    showNextNumber: number,
    canHold: boolean,
    gravity: number,
    lockDelay: number,
    time: number,
    line: number,
    targetLine: number,
    createRubbishInfo: CreateRubbishInfo,
    gameMode: GameModeInfo,
    lastClearLineRafTime: number,
}

const defaultTetrisInfo = (gameMode: string) => {
    return {
        mode: gameMode,
        defaultTetrisCourt: '', // 默认地图
        defaultTetrisCourtLevel: 1, // 默认地图等级
        bagRule: '7Bag', // 方块袋规则
        showNextNumber: 6, // 预览方块个数
        canHold: true,
        gravity: 1 / 64, // 重力 默认为1 / 64 即 每64帧(约1088ms)下落一格
        lockDelay: -1, // 锁定延迟 默认为-1 不开启
        time: 0,
        line: 0,
        targetLine: 0, // 目标行数 打到目标行数后游戏结算
        createRubbishInfo: { // 自动生成垃圾行配置(按时间)
            enable: false, // 是否开启自动创建垃圾行
            frequency: 1, // 生成垃圾行的频率(单位:秒)
            count: 4, // 每次创建数量
            createTimeMode: 'now', // 垃圾行生成时机 默认为立即生成所有垃圾行 delay为分段延迟生成
            mode: 'default', // 垃圾行生成规则
            oneRubbishX: 0, // mode为one时 创建垃圾行的开口的x坐标
            delayInfo: { // 延迟生成配置 createTimeMode为delay时生效
                delay: 10000, // 延迟时间 必须以1000ms为最小单位
                maxCount: 8, // 每次生成最大数量
            }
        },
        autoCreateRubbishInfo: { // 自动生成垃圾行配置(每隔一段时间自动生成垃圾行 且不会经过atkLoader直接生成)
            enable: false, // 是否开启自动创建垃圾行
            count: 1, // 每次创建行数
            airSpan: [1, 1], // 垃圾行开口数量的范围 默认开口1格
            delay: 5000, // 间隔时间 必须以1000ms为最小单位
        },
        confrontModeInfo: {
            enable: false, // 当前为对抗模式
            maxHp: 20, // 最大生命
            hp: 20, // 当前生命
            hpRecoverSpeed: 4000, // 每4000ms 恢复1点生命
        },
        gameMode: {
            name: '',
            id: '',
            desc: '',
            eName: '',
        },
        lastClearLineRafTime: 0, // 最后一次消行的对局时间
        hasLoss: true, // 是否存在游戏失败 关联结算界面
        renLimitInfo: { // 连击到一定次数后 进入限制连击状态 该状态下连击伤害 - 1
            enable: false, // 是否开启连击限制
            limit: 10, // 触发次数
            duration: 10000, // 持续时间 单位ms
            endTime: 0, // 结束时间
        },
        showTotalKey: ['apm', 'lpm', 'apl', 'vs', 'time', 'mode', 'line', 'targetLine'],
        best: 'time', // 最佳成绩判断依据
    }
}

const getTetrisInfo = (gameMode = '') => {
    let tetrisInfo = defaultTetrisInfo(gameMode)
    tetrisInfo = JSON.parse(JSON.stringify(tetrisInfo))
    if (gameMode == 'zen') {
        tetrisInfo.gravity = 0
        tetrisInfo.gameMode = { name: GameMode['zen'], id: 'zen', desc: '无限制', eName: 'ZEN' }
        tetrisInfo.showTotalKey = ['lpm', 'apm', 'apl', 'vs', 'time']
    }
    if (gameMode == '10L') {
        tetrisInfo.targetLine = 10
        tetrisInfo.gameMode = { name: GameMode['10L'], id: '10L', desc: '消除10行', eName: '10 LINES' }
        tetrisInfo.showTotalKey = ['lpm', 'time', 'mode', 'line', 'targetLine']
    }
    if (gameMode == '40L') {
        tetrisInfo.targetLine = 40
        tetrisInfo.gameMode = { name: GameMode['40L'], id: '40L', desc: '消除40行', eName: '40 LINES' }
        tetrisInfo.showTotalKey = ['lpm', 'time', 'mode', 'line', 'targetLine']
    }
    if (gameMode == '200L') {
        tetrisInfo.targetLine = 200
        tetrisInfo.gameMode = { name: GameMode['200L'], id: '200L', desc: '消除200行', eName: '200 LINES' }
        tetrisInfo.showTotalKey = ['lpm', 'time', 'mode', 'line', 'targetLine']
    }
    if (gameMode == '1000L') {
        tetrisInfo.targetLine = 1000
        tetrisInfo.gameMode = { name: GameMode['1000L'], id: '1000L', desc: '消除1000行', eName: '1000 LINES' }
        tetrisInfo.showTotalKey = ['lpm', 'time', 'mode', 'line', 'targetLine']
    }
    if (gameMode == 'confront_lv1') {
        tetrisInfo.createRubbishInfo.enable = true
        tetrisInfo.createRubbishInfo.count = 4
        tetrisInfo.createRubbishInfo.frequency = 5
        tetrisInfo.hasLoss = true // 游戏结束后 正常结算 不显示失败界面
        tetrisInfo.gameMode = { name: GameMode['confront_lv1'], id: 'confront_lv1', desc: '尽可能的存活下来', eName: 'CONFRONT LV1' }
        tetrisInfo.showTotalKey = ['apm', 'lpm', 'apl', 'vs', 'time', 'mode']
        // 48apm
        tetrisInfo.confrontModeInfo.enable = true
        tetrisInfo.confrontModeInfo.maxHp = 20
        tetrisInfo.confrontModeInfo.hp = 20
        tetrisInfo.confrontModeInfo.hpRecoverSpeed = 2000
    }
    if (gameMode == 'confront_lv2') {
        tetrisInfo.createRubbishInfo.enable = true
        tetrisInfo.createRubbishInfo.count = 4
        tetrisInfo.createRubbishInfo.frequency = 4
        tetrisInfo.hasLoss = true
        tetrisInfo.gameMode = { name: GameMode['confront_lv2'], id: 'confront_lv2', desc: '尽可能的存活下来', eName: 'CONFRONT LV2' }
        tetrisInfo.showTotalKey = ['apm', 'lpm', 'apl', 'vs', 'time', 'mode']
        // 60apm
        tetrisInfo.confrontModeInfo.enable = true
        tetrisInfo.confrontModeInfo.maxHp = 40
        tetrisInfo.confrontModeInfo.hp = 40
        tetrisInfo.confrontModeInfo.hpRecoverSpeed = 1500
    }
    if (gameMode == 'confront_lv3') {
        tetrisInfo.createRubbishInfo.enable = true
        tetrisInfo.createRubbishInfo.count = 4
        tetrisInfo.createRubbishInfo.frequency = 4
        tetrisInfo.hasLoss = true
        tetrisInfo.gameMode = { name: GameMode['confront_lv3'], id: 'confront_lv3', desc: '尽可能的存活下来', eName: 'CONFRONT LV3' }
        tetrisInfo.showTotalKey = ['apm', 'lpm', 'apl', 'vs', 'time', 'mode']
        // 60apm
        tetrisInfo.confrontModeInfo.enable = true
        tetrisInfo.confrontModeInfo.maxHp = 100
        tetrisInfo.confrontModeInfo.hp = 100
        tetrisInfo.confrontModeInfo.hpRecoverSpeed = 1500
    }
    if (gameMode == 'confront_lv4') {
        tetrisInfo.createRubbishInfo.enable = true
        tetrisInfo.createRubbishInfo.count = 8
        tetrisInfo.createRubbishInfo.frequency = 4
        tetrisInfo.hasLoss = true
        tetrisInfo.gameMode = { name: GameMode['confront_lv4'], id: 'confront_lv4', desc: '尽可能的存活下来', eName: 'CONFRONT LV4' }
        tetrisInfo.showTotalKey = ['apm', 'lpm', 'apl', 'vs', 'time', 'mode']
        // 120apm
        tetrisInfo.confrontModeInfo.enable = true
        tetrisInfo.confrontModeInfo.maxHp = 200
        tetrisInfo.confrontModeInfo.hp = 200
        tetrisInfo.confrontModeInfo.hpRecoverSpeed = 2000
    }
    if (gameMode == 'one_lv1') {
        tetrisInfo.createRubbishInfo.enable = true
        tetrisInfo.createRubbishInfo.count = 4
        tetrisInfo.createRubbishInfo.frequency = 2.5
        tetrisInfo.createRubbishInfo.mode = 'one'
        tetrisInfo.createRubbishInfo.oneRubbishX = _.random(0, 9) // 开口x坐标
        tetrisInfo.hasLoss = false
        tetrisInfo.gameMode = { name: GameMode['one_lv1'], id: 'one_lv1', desc: '狂 热 消 行', eName: 'ONE LV1' }
        tetrisInfo.showTotalKey = ['apm', 'lpm', 'apl', 'vs', 'time', 'mode']
        tetrisInfo.best = 'clearRubbishLine'
        // 96apm
    }
    if (gameMode == 'one_lv2') {
        tetrisInfo.createRubbishInfo.enable = true
        tetrisInfo.createRubbishInfo.count = 4
        tetrisInfo.createRubbishInfo.frequency = 2
        tetrisInfo.createRubbishInfo.mode = 'one'
        tetrisInfo.createRubbishInfo.oneRubbishX = _.random(0, 9) // 开口x坐标
        tetrisInfo.hasLoss = false
        tetrisInfo.gameMode = { name: GameMode['one_lv2'], id: 'one_lv2', desc: '狂 热 消 行', eName: 'ONE LV2' }
        tetrisInfo.showTotalKey = ['apm', 'lpm', 'apl', 'vs', 'time', 'mode']
        tetrisInfo.best = 'clearRubbishLine'
        // 120apm
    }
    if (gameMode == 'one_lv3') {
        tetrisInfo.createRubbishInfo.enable = true
        tetrisInfo.createRubbishInfo.count = 5
        tetrisInfo.createRubbishInfo.frequency = 2
        tetrisInfo.createRubbishInfo.mode = 'one'
        tetrisInfo.createRubbishInfo.oneRubbishX = _.random(0, 9) // 开口x坐标
        tetrisInfo.hasLoss = false
        tetrisInfo.gameMode = { name: GameMode['one_lv3'], id: 'one_lv3', desc: '狂 热 消 行', eName: 'ONE LV3' }
        tetrisInfo.showTotalKey = ['apm', 'lpm', 'apl', 'vs', 'time', 'mode']
        tetrisInfo.best = 'clearRubbishLine'
        // 150apm
    }
    if (gameMode == 'one_lv4') {
        tetrisInfo.createRubbishInfo.enable = true
        tetrisInfo.createRubbishInfo.count = 10
        tetrisInfo.createRubbishInfo.frequency = 3.5
        tetrisInfo.createRubbishInfo.mode = 'one'
        tetrisInfo.createRubbishInfo.oneRubbishX = _.random(0, 9) // 开口x坐标
        tetrisInfo.hasLoss = false
        tetrisInfo.gameMode = { name: GameMode['one_lv4'], id: 'one_lv4', desc: '狂 热 消 行', eName: 'ONE LV4' }
        tetrisInfo.showTotalKey = ['apm', 'lpm', 'apl', 'vs', 'time', 'mode']
        tetrisInfo.best = 'clearRubbishLine'
        // 171apm
    }
    if (gameMode == 'survival_lv1') {
        // 生存模式
        tetrisInfo.createRubbishInfo.enable = true
        tetrisInfo.createRubbishInfo.count = 8
        tetrisInfo.createRubbishInfo.frequency = 6
        tetrisInfo.createRubbishInfo.createTimeMode = 'delay'
        tetrisInfo.createRubbishInfo.delayInfo = {
            delay: 10000,
            maxCount: 20,
        }
        tetrisInfo.hasLoss = false
        tetrisInfo.gameMode = { name: GameMode['survival_lv1'], id: 'survival_lv1', desc: '尽可能的存活下来', eName: 'SURVIVAL LV1' }
        tetrisInfo.showTotalKey = ['apm', 'lpm', 'apl', 'vs', 'time', 'mode']
        tetrisInfo.best = 'clearRubbishLine'
        // 80apm 每10秒生成一次垃圾行 一次最多生成8行
    }
    if (gameMode == 'survival_lv2') {
        tetrisInfo.createRubbishInfo.enable = true
        tetrisInfo.createRubbishInfo.count = 8
        tetrisInfo.createRubbishInfo.frequency = 5
        tetrisInfo.createRubbishInfo.createTimeMode = 'delay'
        tetrisInfo.createRubbishInfo.delayInfo = {
            delay: 12000,
            maxCount: 10,
        }
        tetrisInfo.hasLoss = false
        tetrisInfo.gameMode = { name: GameMode['survival_lv2'], id: 'survival_lv2', desc: '尽可能的存活下来', eName: 'SURVIVAL LV2' }
        tetrisInfo.showTotalKey = ['apm', 'lpm', 'apl', 'vs', 'time', 'mode']
        tetrisInfo.best = 'clearRubbishLine'
        // 96apm 每6秒生成一次垃圾行 一次最多生成8行
    }
    if (gameMode == 'survival_lv3') {
        tetrisInfo.createRubbishInfo.enable = true
        tetrisInfo.createRubbishInfo.count = 12
        tetrisInfo.createRubbishInfo.frequency = 6
        tetrisInfo.createRubbishInfo.createTimeMode = 'delay'
        tetrisInfo.createRubbishInfo.delayInfo = {
            delay: 10000,
            maxCount: 10,
        }
        tetrisInfo.hasLoss = false
        tetrisInfo.gameMode = { name: GameMode['survival_lv3'], id: 'survival_lv3', desc: '尽可能的存活下来', eName: 'SURVIVAL LV3' }
        tetrisInfo.showTotalKey = ['apm', 'lpm', 'apl', 'vs', 'time', 'mode']
        tetrisInfo.best = 'clearRubbishLine'
        // 120apm 每3秒生成一次垃圾行 一次最多生成8行
    }
    if (gameMode == 'survival_lv4') {
        tetrisInfo.createRubbishInfo.enable = true
        tetrisInfo.createRubbishInfo.count = 24
        tetrisInfo.createRubbishInfo.frequency = 10
        tetrisInfo.createRubbishInfo.createTimeMode = 'delay'
        tetrisInfo.createRubbishInfo.delayInfo = {
            delay: 8000,
            maxCount: 16,
        }
        tetrisInfo.hasLoss = false
        tetrisInfo.gameMode = { name: GameMode['survival_lv4'], id: 'survival_lv4', desc: '尽可能的存活下来', eName: 'SURVIVAL LV4' }
        tetrisInfo.showTotalKey = ['apm', 'lpm', 'apl', 'vs', 'time', 'mode']
        tetrisInfo.best = 'clearRubbishLine'
        // 144apm 每4秒生成一次垃圾行 一次最多生成10行
    }
    if (gameMode == 'excavate_lv1') {
        tetrisInfo.targetLine = 100
        tetrisInfo.autoCreateRubbishInfo.enable = true
        tetrisInfo.autoCreateRubbishInfo.count = 1
        tetrisInfo.autoCreateRubbishInfo.delay = 5000
        tetrisInfo.autoCreateRubbishInfo.airSpan = [1, 3]
        tetrisInfo.gameMode = { name: GameMode['excavate_lv1'], id: 'excavate_lv1', desc: '向下挖掘！', eName: 'EXCAVATE LV1' }
        tetrisInfo.defaultTetrisCourt = 'excavate'
        tetrisInfo.defaultTetrisCourtLevel = 4
        tetrisInfo.showTotalKey = ['lpm', 'time', 'mode', 'line', 'targetLine']
    }
    if (gameMode == 'excavate_lv2') {
        tetrisInfo.targetLine = 200
        tetrisInfo.autoCreateRubbishInfo.enable = true
        tetrisInfo.autoCreateRubbishInfo.count = 1
        tetrisInfo.autoCreateRubbishInfo.delay = 4000
        tetrisInfo.autoCreateRubbishInfo.airSpan = [1, 3]
        tetrisInfo.gameMode = { name: GameMode['excavate_lv2'], id: 'excavate_lv2', desc: '向下挖掘！', eName: 'EXCAVATE LV2' }
        tetrisInfo.defaultTetrisCourt = 'excavate'
        tetrisInfo.defaultTetrisCourtLevel = 4
        tetrisInfo.showTotalKey = ['lpm', 'time', 'mode', 'line', 'targetLine']
    }
    if (gameMode == 'excavate_lv3') {
        tetrisInfo.targetLine = 200
        tetrisInfo.autoCreateRubbishInfo.enable = true
        tetrisInfo.autoCreateRubbishInfo.count = 2
        tetrisInfo.autoCreateRubbishInfo.delay = 8000
        tetrisInfo.autoCreateRubbishInfo.airSpan = [2, 4]
        tetrisInfo.gameMode = { name: GameMode['excavate_lv3'], id: 'excavate_lv3', desc: '向下挖掘！', eName: 'EXCAVATE LV3' }
        tetrisInfo.defaultTetrisCourt = 'excavate'
        tetrisInfo.defaultTetrisCourtLevel = 4
        tetrisInfo.showTotalKey = ['lpm', 'time', 'mode', 'line', 'targetLine']
    }
    if (gameMode == 'excavate_lv4') {
        tetrisInfo.targetLine = 500
        tetrisInfo.autoCreateRubbishInfo.enable = true
        tetrisInfo.autoCreateRubbishInfo.count = 2
        tetrisInfo.autoCreateRubbishInfo.delay = 7000
        tetrisInfo.autoCreateRubbishInfo.airSpan = [4, 8]
        tetrisInfo.gameMode = { name: GameMode['excavate_lv4'], id: 'excavate_lv4', desc: '向下挖掘！', eName: 'EXCAVATE LV4' }
        tetrisInfo.defaultTetrisCourt = 'excavate'
        tetrisInfo.defaultTetrisCourtLevel = 4
        tetrisInfo.showTotalKey = ['lpm', 'time', 'mode', 'line', 'targetLine']
    }
    if (gameMode == 'classic') {
        tetrisInfo.gravity = 0.5 // 1倍重力
        tetrisInfo.lockDelay = 2000 // 锁定延迟 2000ms
        tetrisInfo.bagRule = 'random' // 随机
        tetrisInfo.showNextNumber = 1
        tetrisInfo.canHold = false
        tetrisInfo.hasLoss = false
        tetrisInfo.gameMode = { name: GameMode['classic'], id: 'classic', desc: '经典模式', eName: 'CLASSIC' }
        tetrisInfo.showTotalKey = ['lpm', 'time', 'mode', 'line']
    }
    if (gameMode == 'quickMatch') {
        tetrisInfo.showTotalKey = ['apm', 'lpm', 'apl', 'vs', 'time']
        tetrisInfo.gameMode = { name: GameMode['quickMatch'], id: 'quickMatch', desc: '快速匹配', eName: 'QuickMatch' }
        tetrisInfo.best = 'vs'
    }
    return tetrisInfo
}

const getClearLineInfo = (params: any) => {
    let {
        btb = false,
        hasClearLine = 0,
        hasClearRubbishLine = 0,
        hasTSpin = false,
        ren = 0,
        result = [],
        tetrisTotal
    } = params
    let skillText = ''
    let playAudioName = 'down'
    let resultBtb = false
    let atk = 0
    let renAtk = 0
    if (hasClearLine == 1) {
        playAudioName = 'c1'
        if (!hasTSpin) tetrisTotal.single += 1
    }
    else if (hasClearLine == 2) {
        playAudioName = 'c2'
        atk = 1
        if (!hasTSpin) tetrisTotal.double += 1
    }
    else if (hasClearLine == 3) {
        playAudioName = 'c3'
        atk = 2
        if (!hasTSpin) tetrisTotal.triple += 1
    }
    else if (hasClearLine == 4) {
        playAudioName = 'c4'
        skillText = 'Tetris'
        atk = 4
        if (btb) {
            playAudioName = 'c4b'
            skillText = 'BTB Tetris'
            atk = 5
            tetrisTotal.btbTetris += 1
        }
        else tetrisTotal.tetris += 1
        resultBtb = true
    }
    if (hasTSpin) {
        tetrisTotal.tspin += 1
        if (hasClearLine == 1) {
            playAudioName = 't1'
            skillText = 'Tspin single'
            atk = 2
            if (btb) {
                playAudioName = 't1b'
                skillText = 'BTB Tspin single'
                atk = 3
                tetrisTotal.btbTspinSingle += 1
            }
            else tetrisTotal.tspinSingle += 1
        }
        else if (hasClearLine == 2) {
            playAudioName = 't2'
            atk = 4
            skillText = 'Tspin double'
            if (btb) {
                playAudioName = 't2b'
                skillText = 'BTB Tspin double'
                atk = 5
                tetrisTotal.btbTspinDouble += 1
            }
            else tetrisTotal.tspinDouble += 1
        }
        else if (hasClearLine == 3) {
            playAudioName = 't3'
            skillText = 'Tspin triple'
            atk = 6
            if (btb) {
                playAudioName = 't3b'
                skillText = 'BTB Tspin triple'
                atk = 8
                tetrisTotal.btbTspinTriple += 1
            }
            else tetrisTotal.tspinTriple += 1
        }
        if (hasClearLine) resultBtb = true
    }
    if (result.length == 0) {
        // 全消
        atk += 10
        playAudioName = 'ac'
        skillText = 'ALL CLEAR'
        resultBtb = true
        tetrisTotal.allClear += 1
    }
    if (ren == 2 || ren == 3) renAtk = 1
    if (ren == 4 || ren == 5) renAtk = 2
    if (ren == 6 || ren == 7) renAtk = 3
    if (ren == 8 || ren == 9 || ren == 10) renAtk = 4
    if (ren > 11) renAtk = 5
    if (btb && resultBtb) tetrisTotal.btb += 1
    if (ren > tetrisTotal.maxCombo) tetrisTotal.maxCombo = ren
    if (hasClearLine) tetrisTotal.clearLine += hasClearLine
    if (hasClearRubbishLine) tetrisTotal.clearRubbishLine += hasClearRubbishLine
    if (atk) tetrisTotal.atkTotal += atk
    if (renAtk) tetrisTotal.atkTotal += renAtk
    return {
        playAudioName,
        skillText,
        btb: resultBtb,
        atk,
        renAtk,
        tetrisTotal,
    }
}

const createRubbishLine = (fixed = [] as any, totalAtk = [] as any, createRubbishInfo: CreateRubbishInfo) => {
    // fixed 当前场地信息
    // totalAtk 累计攻击行数组
    // createRubbishInfo.createTimeMode 垃圾行生成时机 now: 立即生成所有垃圾行 delay: 分段生成
    // createRubbishInfo.mode 垃圾行生成规则对象
    let _fixed = JSON.parse(JSON.stringify(fixed))
    let result = {
        resultFixed: [] as any, // 最终场地信息
        gameover: false, // 游戏结束
        restAtk: [], // 剩余攻击行
    }
    let rubbishColor = mino.find((i: any) => i.type == 'rubbish').color
    if (totalAtk && totalAtk.length) {
        const total = totalAtk.reduce((pre: number, item: any) => pre + item.num, 0)
        result.resultFixed = _fixed.map((i: any) => {
            i.y -= total
            return i
        })
        let renderY = 19 // 当前渲染的垃圾行y坐标
        // 先反向数组 再遍历
        totalAtk.reverse().forEach((item: any) => {
            let openX = 0
            if (createRubbishInfo && createRubbishInfo.mode == 'one') openX = createRubbishInfo.oneRubbishX // 开口位置固定
            else openX = _.random(0, 9, false) // 随机开口位置
            for (let index = 0; index < item.num; index++) {
                for (let x = 0; x < 10; x++) {
                    if (x == openX) continue // 开口
                    result.resultFixed.push({
                        x,
                        y: renderY,
                        color: rubbishColor,
                        type: 'rubbish',
                    })
                }
                renderY--
            }
        })
        // console.log('result', result)
    }
    return result
    // 需调用updateFixedCourtIndex为垃圾行添加场地index
}

// 挖掘模式专用 生成垃圾行
const autoCreateRubbishLine = (target = [], fixed = [] as any, totalAtk = 0, airSpan = [1, 1]) => {
    // fixed 当前场地信息
    // totalAtk 新增垃圾行总行数
    // airSpan 垃圾行开口数量范围 默认为1
    let _fixed = JSON.parse(JSON.stringify(fixed))
    let _target = JSON.parse(JSON.stringify(target))
    let result = {
        resultFixed: [] as any, // 最终场地信息
        resultTarget: [] as any, // 最终当前块信息
        gameover: false, // 游戏结束
        restAtk: [], // 剩余攻击行
    }
    let rubbishColor = mino.find((i: any) => i.type == 'rubbish').color
    result.resultTarget = _target.map((i: any) => { // 将当前块整体上移
        i.y -= totalAtk
        return i
    })
    result.resultFixed = _fixed.map((i: any) => { // 将原本场地整体上移
        i.y -= totalAtk
        if (i.y < 0 && i.x > 2 && i.x < 7) result.gameover = true // 游戏结束
        return i
    })
    let renderY = 19 // 当前渲染的垃圾行y坐标
    for (let index = 0; index < totalAtk; index++) {
        let openNumber = _.random(airSpan[0], airSpan[1], false) // 随机开口数量
        let openX = []
        for (let i = 0; i < openNumber; i++) {
            openX.push(_.random(0, 9, false))
        }
        for (let x = 0; x < 10; x++) {
            if (openX.includes(x)) continue // 开口
            result.resultFixed.push({
                x,
                y: renderY,
                color: rubbishColor,
                type: 'rubbish',
            })
        }
        renderY--
    }
    return result
    // 需调用updateFixedCourtIndex为垃圾行添加场地index
}

// 初始化方块场地 在场地中添加初始化方块
const initTetrisCourt = (type = '', level = 1) => {
    let fixed = [] as any
    let renderRule = defaultCourt(type, level) as any
    let rubbishColor = mino.find((i: any) => i.type == 'build').color
    renderRule.forEach((i: any) => {
        const yList = i.y.length == 1 ? i.y : fullArray(i.y[0], i.y[1])
        let x = [] as any
        if (i.val.isRandom) {
            for (let index = 0; index < i.val.openNumber; index++) {
                x.push(_.random(0, 9, false)) // 随机坐标
            }
        }
        else x = i.val.x
        yList.forEach((y: number) => {
            if (i.mode == 'air') { // 开口模式
                for (let renderX = 0; renderX < 10; renderX++) {
                    if (x.includes(renderX)) continue // 开口
                    fixed.push({
                        x: renderX,
                        y,
                        color: rubbishColor,
                        type: 'rubbish',
                    })
                }
            }
            else { // 填充模式
                x.forEach((renderX: number) => {
                    fixed.push({
                        x: renderX,
                        y,
                        color: rubbishColor,
                        type: 'rubbish',
                    })
                })
            }
        })
    })
    return fixed
}

interface Atk {
    num: number // 攻击条数量
    time: number // 受到攻击的时间
}

interface LoadingAtk {
    num: number // 攻击条数量
    time: number // 受到攻击的时间
    restTime: number // 剩余时间
}

interface AtkLoaderInitParams {
    mode: 'now' | 'delay'
    LoadTime: number,
    MaxLoadNumber: number,
    LoadEndCallback: () => void
}


// 攻击加载器
class AtkLoader {

    atk: Atk[] = [] // 已准备就绪的攻击条
    loadingAtk: LoadingAtk[] = [] // 加载中的攻击条
    mode: 'now' | 'delay' = 'now' // 垃圾行加载模式
    private LoadRubbishTimer: any = false // 加载垃圾行定时器
    private Loading = false // 加载中
    private LoadTime = 0 // 垃圾行加载需要的时间 
    private MaxLoadNumber = 0 // 最大加载垃圾行数量
    private LoadEndCallback: () => void = () => { } // 加载完成回调
    changeCb = () => { }

    constructor() {
        this.atk = []
        this.loadingAtk = []
    }

    // 就绪攻击累计
    get atkTotal() {
        return this.atk.reduce((i, j) => i + j.num, 0)
    }

    // 加载中攻击累计
    get loadingAtkTotal() {
        return this.loadingAtk.reduce((i, j) => i + j.num, 0)
    }

    // 存在累计垃圾行
    get hasAtk() {
        return this.atkTotal + this.loadingAtkTotal > 0
    }

    init(params: AtkLoaderInitParams) {
        this.atk = []
        this.loadingAtk = []
        Object.assign(this, params)
        if (this.LoadRubbishTimer) clearTimeout(this.LoadRubbishTimer)
        this.LoadRubbishTimer = false
        this.Loading = false
    }

    // 添加 已准备就绪垃圾行
    addAtk(num: number) {
        if (this.mode == 'now') {
            this.atk.push({
                num,
                time: dayjs().valueOf(),
            })
        }
        else {
            this.loadingAtk.push({
                num,
                time: dayjs().valueOf(),
                restTime: this.LoadTime,
            })
            this.initLoadRubbishTimer()
        }
        this.changeCb()
    }

    // 初始化加载垃圾行定时器 load: 是否为递归调用
    initLoadRubbishTimer(load = false) {
        if ((this.Loading && !load) || this.loadingAtk.length == 0) return
        this.Loading = true
        // 每秒加载一次
        this.LoadRubbishTimer = setTimeout(() => {
            let loadingAtk = this.loadingAtk
            loadingAtk = loadingAtk.map((atk) => {
                atk.restTime -= 1000
                if (atk.restTime <= 0) { // 加载完成后 加入到已准备就绪的攻击条
                    let isCanAdd = true
                    if (this.MaxLoadNumber <= this.atkTotal) {
                        isCanAdd = false // 已就绪的垃圾行超过最大数量时 进行等待
                    }
                    else if ((this.MaxLoadNumber > this.atkTotal) && (this.MaxLoadNumber < (this.atkTotal + atk.num))) {
                        // 当前加载的垃圾行加入后 超过最大数量 分割
                        let addAtkNumber = this.MaxLoadNumber - this.atkTotal // 可加入的垃圾行数量
                        atk.num = atk.num - addAtkNumber
                        this.atk.push({
                            num: addAtkNumber,
                            time: dayjs().valueOf(),
                        })
                        this.LoadEndCallback()
                        isCanAdd = false
                    }
                    if (isCanAdd) { // 可加入
                        if (atk.num) {
                            this.atk.push({
                                num: atk.num,
                                time: dayjs().valueOf(),
                            })
                            atk.num = 0
                            this.LoadEndCallback()
                        }
                    }
                }
                return atk
            })
            loadingAtk = loadingAtk.filter((atk) => atk.num > 0)
            if (this.loadingAtk.length) this.initLoadRubbishTimer(true) // 继续加载
            else this.Loading = false
        }, 1000)
    }

    // 消耗所有已准备就绪垃圾行
    handleLoadAtk() {
        let total = this.atkTotal
        this.atk = []
        this.changeCb()
        return total
    }

    // 抵消垃圾行 返回抵消剩余的攻击数
    counteract(num: number) {
        let flag = 0
        // 无延迟垃圾行
        if (this.mode == 'now') {
            while (num > 0 && this.atk.length && flag < 1000) {
                let lassItem = this.atk[this.atk.length - 1]
                if (lassItem.num > num) {
                    this.atk[this.atk.length - 1].num -= num // 抵消
                    num = 0
                }
                else if (lassItem.num == num) {
                    this.atk.pop() // 抵消
                    num = 0
                }
                else {
                    this.atk.pop() // 抵消
                    num -= lassItem.num
                }
                flag++
            }
            return num
        }
        // 延迟垃圾行
        else {
            while (num > 0 && (this.atk.length || this.loadingAtk.length) && flag < 1000) {
                // 存在已就绪垃圾行 优先抵消
                if (this.atkTotal) {
                    let lassItem = this.atk[this.atk.length - 1]
                    if (lassItem.num > num) {
                        this.atk[this.atk.length - 1].num -= num // 抵消
                        num = 0
                    }
                    else if (lassItem.num == num) {
                        this.atk.pop() // 抵消
                        num = 0
                    }
                    else {
                        this.atk.pop() // 抵消
                        num -= lassItem.num
                    }
                }
                // 不存在已就绪垃圾行 存在加载中垃圾行 抵消
                else if (this.loadingAtkTotal) {
                    let lassItem = this.loadingAtk[this.loadingAtk.length - 1]
                    if (lassItem.num > num) {
                        this.loadingAtk[this.loadingAtk.length - 1].num -= num // 抵消
                        num = 0
                    }
                    else if (lassItem.num == num) {
                        this.loadingAtk.pop() // 抵消
                        num = 0
                    }
                    else {
                        this.loadingAtk.pop() // 抵消
                        num -= lassItem.num
                    }
                }
                flag++
            }
            return num
        }
        this.changeCb()
    }

}

// 锁定延迟定时器
class LockDelayTimer {

    timer = null as any
    lockDelay = 0
    cb = () => { }
    status = 0 // 允许状态 0: 未进行 1: 进行中 2: 已准备就绪

    init(lockDelay: number, cb = () => { }) {
        this.timer = new RafTimer()
        this.timer.init()
        this.lockDelay = lockDelay
        this.cb = cb
        this.status = 0
        this.timer.setCb(() => { // 使用箭头函数 防止this指向改变
            this.run()
        })
    }

    reset(init = false) {
        this.timer.init()
        if (init) this.status = 0
    }

    run() {
        if (this.timer.rafTime >= this.lockDelay) {
            this.status = 2
            this.pause()
            this.cb()
            this.reset()
        }
    }

    start() {
        if (this.timer) {
            this.timer.start()
            this.status = 1
        }
    }

    pause() {
        if (this.timer) this.timer.pause()
    }

    // 进度 单位: 百分比 初始值为100 结束为0
    get progress() {
        let res = this.timer && this.timer.rafTime ? (100 - this.timer.rafTime / this.lockDelay * 100) : 0
        return res < 0 ? 0 : res
    }

}


export {
    GameMode,
    singleModeList,
    getTetrisInfo,
    getClearLineInfo,
    createRubbishLine,
    autoCreateRubbishLine,
    initTetrisCourt,
    AtkLoader,
    LockDelayTimer,
}
